﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using Athena.Core;

namespace Athena.Objects
{
    [Serializable]
    public class PerturbationGlyph : IGlyph
    {

        public PerturbationGlyph(PerturbationGlyph copy)
        {
            _Location = copy._Location;
            _Dimensions = copy._Dimensions;
            Text = copy.Text;
            if (copy.Item != null)
                Item = copy.Item.Clone() as Item;
        }
        public PerturbationGlyph(PointF location)
            : this()
        {
            _Location = new PointF(location.X - 10, location.Y - 10);
            Item = new Species("perturbation", "P_0", 0);
        }

        public PerturbationGlyph()
        {
            _Dimensions = new System.Drawing.SizeF(40f, 20f);
            ColorStart = Color.White;
            ColorEnd = Color.Silver;
            EdgeColor = Color.Black;

            TextColor = Color.Black;
            Text = "P_0";
        }

        public override bool HasPreview
        {
            get
            {
                return true;
            }
        }



        public override Bitmap GetPreview(int width, int height)
        {
            Bitmap oBmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(oBmp);
            PerturbationGlyph oGlyph = new PerturbationGlyph();
            oGlyph.Location = new PointF(2f, 5f);
            oGlyph.Dimensions = new SizeF(15f, 8f);
            oGlyph.RenderGlyph(g);
            return oBmp;
        }

        public override void RenderGlyph(Graphics g)
        {

            Pen oOutline = new Pen(EdgeColor, EdgeThickness);
            Brush oFilled;
            if (_oFillColorStart == _oFillColorEnd || _Dimensions.Width < 2 || _Dimensions.Height < 2)
                oFilled = new SolidBrush(_oFillColorStart);
            else
                oFilled = new LinearGradientBrush(Location, new PointF(Location.X + Dimensions.Width, Location.Y + Dimensions.Height), _oFillColorStart, _oFillColorEnd);

            GraphicsPath oPath = new GraphicsPath();
            float fPercentage = 0.8f;
            oPath.StartFigure();
            oPath.AddLine(Location.X, Location.Y, Location.X + Dimensions.Width, Location.Y);
            oPath.AddLine(Location.X + Dimensions.Width, Location.Y, Location.X + Dimensions.Width * fPercentage, Location.Y + Dimensions.Height / 2f);
            oPath.AddLine(Location.X + Dimensions.Width * fPercentage, Location.Y + Dimensions.Height / 2f, Location.X + Dimensions.Width, Location.Y + Dimensions.Height);
            oPath.AddLine(Location.X + Dimensions.Width, Location.Y + Dimensions.Height, Location.X, Location.Y + Dimensions.Height);
            oPath.AddLine(Location.X, Location.Y + Dimensions.Height, Location.X + Dimensions.Width * (1f - fPercentage), Location.Y + Dimensions.Height / 2f);
            oPath.AddLine(Location.X + Dimensions.Width * (1f - fPercentage), Location.Y + Dimensions.Height / 2f, Location.X, Location.Y);
            oPath.CloseFigure();

            g.FillPath(oFilled, oPath);

            if (ShowCloneMarker)
            {

                LinearGradientBrush oBrush = new LinearGradientBrush(Bounds, Color.Transparent, CloneMarkerColor, LinearGradientMode.Vertical);
                ColorBlend oBlend = new ColorBlend(2);
                oBlend.Positions = new float[] { 0f, 1f - ClonePercentage, 1f - ClonePercentage, 1f };
                oBlend.Colors = new Color[] { Color.Transparent, Color.Transparent, CloneMarkerColor, CloneMarkerColor };
                oBrush.InterpolationColors = oBlend;
                g.FillPath(oBrush, oPath);
                DrawCloneMarkerText(g);
            }

            g.DrawPath(oOutline, oPath);

        }

        public override object Clone()
        {
            return new PerturbationGlyph(this);
        }

        public override SBMLExtension.EmlRenderExtension.LocalStyle ToStyle(SBMLExtension.EmlRenderExtension.RenderInformation oInfo)
        {
            SBMLExtension.EmlRenderExtension.LocalStyle oResult = new SBMLExtension.EmlRenderExtension.LocalStyle();
            SBMLExtension.EmlRenderExtension.Group oGroup = new SBMLExtension.EmlRenderExtension.Group();
            oGroup.Stroke = oInfo.AddColorDefinition(_oEdgeColor);
            oGroup.StrokeWidth = _dEdgeThickness.ToString();
            if (_oFillColorStart == _oFillColorEnd)
                oGroup.Fill = oInfo.AddColorDefinition(_oFillColorStart);
            else
                oGroup.Fill = oInfo.AddLinearGradientDefinition(_oFillColorStart, _oFillColorEnd);

            SBMLExtension.EmlRenderExtension.Polygon oPolygon = new SBMLExtension.EmlRenderExtension.Polygon();
            oPolygon.Fill = oGroup.Fill;
            oPolygon.Stroke = oGroup.Stroke;
            oPolygon.StrokeWidth = oGroup.StrokeWidth;
            float fPercentage = 0.8f;

            float left = 0f; float top = 0f;

            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left, top),
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top),
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * fPercentage, top + Dimensions.Height / 2f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * fPercentage, top + Dimensions.Height / 2f),
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top + Dimensions.Height)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top + Dimensions.Height),
                new SBMLExtension.LayoutExtension.Point(left, top + Dimensions.Height)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left, top + Dimensions.Height),
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * (1f - fPercentage), top + Dimensions.Height / 2f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * (1f - fPercentage), top + Dimensions.Height / 2f),
                new SBMLExtension.LayoutExtension.Point(left, top)
                ));

            oGroup.Children.Add(oPolygon);

            if (ShowCloneMarker)
            {
                AddCloneMarkerGradient(oInfo);

                SBMLExtension.EmlRenderExtension.Polygon oPolygon2 = new SBMLExtension.EmlRenderExtension.Polygon();

                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left, top),
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top)
                    ));
                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top),
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * fPercentage, top + Dimensions.Height / 2f)
                    ));
                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * fPercentage, top + Dimensions.Height / 2f),
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top + Dimensions.Height)
                    ));
                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width, top + Dimensions.Height),
                    new SBMLExtension.LayoutExtension.Point(left, top + Dimensions.Height)
                    ));
                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left, top + Dimensions.Height),
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * (1f - fPercentage), top + Dimensions.Height / 2f)
                    ));
                oPolygon2.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(left + Dimensions.Width * (1f - fPercentage), top + Dimensions.Height / 2f),
                    new SBMLExtension.LayoutExtension.Point(left, top)
                    ));

                oPolygon2.Fill = "cloneMarker";
                oGroup.Children.Add(oPolygon2);

            }


            AddLabelGlyph(oInfo, oGroup);

            oResult.Group = oGroup;
            return oResult;

        }
    }
}
